home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 039a / jpsrc2.zip / JRDRLE.C < prev    next >
C/C++ Source or Header  |  1991-11-30  |  12KB  |  373 lines

  1. /*
  2.  * jrdrle.c
  3.  *
  4.  * Copyright (C) 1991, Thomas G. Lane.
  5.  * This file is part of the Independent JPEG Group's software.
  6.  * For conditions of distribution and use, see the accompanying README file.
  7.  *
  8.  * This file contains routines to read input images in Utah RLE format.
  9.  * The Utah Raster Toolkit library is required (version 3.0).
  10.  *
  11.  * These routines may need modification for non-Unix environments or
  12.  * specialized applications.  As they stand, they assume input from
  13.  * an ordinary stdio stream.  They further assume that reading begins
  14.  * at the start of the file; input_init may need work if the
  15.  * user interface has already read some data (e.g., to determine that
  16.  * the file is indeed RLE format).
  17.  *
  18.  * These routines are invoked via the methods get_input_row
  19.  * and input_init/term.
  20.  *
  21.  * Based on code contributed by Mike Lijewski.
  22.  */
  23.  
  24. #include "jinclude.h"
  25.  
  26. #ifdef RLE_SUPPORTED
  27.  
  28. /* rle.h is provided by the Utah Raster Toolkit. */
  29.  
  30. #include <rle.h>
  31.  
  32.  
  33. /*
  34.  * load_image assumes that JSAMPLE has the same representation as rle_pixel,
  35.  * to wit, "unsigned char".  Hence we can't cope with 12- or 16-bit samples.
  36.  */
  37.  
  38. #ifndef EIGHT_BIT_SAMPLES
  39.   Sorry, this code only copes with 8-bit JSAMPLEs. /* deliberate syntax err */
  40. #endif
  41.  
  42.  
  43. /*
  44.  * We support the following types of RLE files:
  45.  *   
  46.  *   GRAYSCALE   - 8 bits, no colormap
  47.  *   PSEUDOCOLOR - 8 bits, colormap
  48.  *   TRUECOLOR   - 24 bits, colormap
  49.  *   DIRECTCOLOR - 24 bits, no colormap
  50.  *
  51.  * For now, we ignore any alpha channel in the image.
  52.  */
  53.  
  54. typedef enum { GRAYSCALE, PSEUDOCOLOR, TRUECOLOR, DIRECTCOLOR } rle_kind;
  55.  
  56. static rle_kind visual;        /* actual type of input file */
  57.  
  58. /*
  59.  * Since RLE stores scanlines bottom-to-top, we have to invert the image
  60.  * to conform to JPEG's top-to-bottom order.  To do this, we read the
  61.  * incoming image into a virtual array on the first get_input_row call,
  62.  * then fetch the required row from the virtual array on subsequent calls.
  63.  */
  64.  
  65. static big_sarray_ptr image;    /* single array for GRAYSCALE/PSEUDOCOLOR */
  66. static big_sarray_ptr red_channel; /* three arrays for TRUECOLOR/DIRECTCOLOR */
  67. static big_sarray_ptr green_channel;
  68. static big_sarray_ptr blue_channel;
  69. static long cur_row_number;    /* last row# read from virtual array */
  70.  
  71. static rle_hdr header;        /* Input file information */
  72. static rle_map *colormap;    /* RLE colormap, if any */
  73.  
  74.  
  75. /*
  76.  * Read the file header; return image size and component count.
  77.  */
  78.  
  79. METHODDEF void
  80. input_init (compress_info_ptr cinfo)
  81. {
  82.   long width, height;
  83.  
  84.   /* Use RLE library routine to get the header info */
  85.   header.rle_file = cinfo->input_file;
  86.   switch (rle_get_setup(&header)) {
  87.   case RLE_SUCCESS:
  88.     /* A-OK */
  89.     break;
  90.   case RLE_NOT_RLE:
  91.     ERREXIT(cinfo->emethods, "Not an RLE file");
  92.     break;
  93.   case RLE_NO_SPACE:
  94.     ERREXIT(cinfo->emethods, "Insufficient memory for RLE header");
  95.     break;
  96.   case RLE_EMPTY:
  97.     ERREXIT(cinfo->emethods, "Empty RLE file");
  98.     break;
  99.   case RLE_EOF:
  100.     ERREXIT(cinfo->emethods, "Premature EOF in RLE header");
  101.     break;
  102.   default:
  103.     ERREXIT(cinfo->emethods, "Bogus RLE error code");
  104.     break;
  105.   }
  106.  
  107.   /* Figure out what we have, set private vars and return values accordingly */
  108.   
  109.   width  = header.xmax - header.xmin + 1;
  110.   height = header.ymax - header.ymin + 1;
  111.   header.xmin = 0;        /* realign horizontally */
  112.   header.xmax = width-1;
  113.  
  114.   cinfo->image_width      = width;
  115.   cinfo->image_height     = height;
  116.   cinfo->data_precision   = 8;  /* we can only handle 8 bit data */
  117.  
  118.   if (header.ncolors == 1 && header.ncmap == 0) {
  119.     visual     = GRAYSCALE;
  120.     TRACEMS(cinfo->emethods, 1, "Gray-scale RLE file");
  121.   } else if (header.ncolors == 1 && header.ncmap == 3) {
  122.     visual     = PSEUDOCOLOR;
  123.     colormap   = header.cmap;
  124.     TRACEMS1(cinfo->emethods, 1, "Colormapped RLE file with map of length %d",
  125.          1 << header.cmaplen);
  126.   } else if (header.ncolors == 3 && header.ncmap == 3) {
  127.     visual     = TRUECOLOR;
  128.     colormap   = header.cmap;
  129.     TRACEMS1(cinfo->emethods, 1, "Full-color RLE file with map of length %d",
  130.          1 << header.cmaplen);
  131.   } else if (header.ncolors == 3 && header.ncmap == 0) {
  132.     visual     = DIRECTCOLOR;
  133.     TRACEMS(cinfo->emethods, 1, "Full-color RLE file");
  134.   } else
  135.     ERREXIT(cinfo->emethods, "Can't handle this RLE setup");
  136.   
  137.   switch (visual) {
  138.   case GRAYSCALE:
  139.     /* request one big array to hold the grayscale image */
  140.     image = (*cinfo->emethods->request_big_sarray) (width, height, 1L);
  141.     cinfo->in_color_space   = CS_GRAYSCALE;
  142.     cinfo->input_components = 1;
  143.     break;
  144.   case PSEUDOCOLOR:
  145.     /* request one big array to hold the pseudocolor image */
  146.     image = (*cinfo->emethods->request_big_sarray) (width, height, 1L);
  147.     cinfo->in_color_space   = CS_RGB;
  148.     cinfo->input_components = 3;
  149.     break;
  150.   case TRUECOLOR:
  151.   case DIRECTCOLOR:
  152.     /* request three big arrays to hold the RGB channels */
  153.     red_channel   = (*cinfo->emethods->request_big_sarray) (width, height, 1L);
  154.     green_channel = (*cinfo->emethods->request_big_sarray) (width, height, 1L);
  155.     blue_channel  = (*cinfo->emethods->request_big_sarray) (width, height, 1L);
  156.     cinfo->in_color_space   = CS_RGB;
  157.     cinfo->input_components = 3;
  158.     break;
  159.   }
  160. }
  161.  
  162.  
  163. /*
  164.  * Read one row of pixels.
  165.  * These are called only after load_image has read the image into
  166.  * the virtual array(s).
  167.  */
  168.  
  169.  
  170. METHODDEF void
  171. get_grayscale_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
  172. /* This is used for GRAYSCALE images */
  173. {
  174.   JSAMPROW inputrows[1];    /* a pseudo JSAMPARRAY structure */
  175.  
  176.   cur_row_number--;        /* work down in array */
  177.   
  178.   inputrows[0] = *((*cinfo->emethods->access_big_sarray)
  179.             (image, cur_row_number, FALSE));
  180.  
  181.   jcopy_sample_rows(inputrows, 0, pixel_row, 0, 1, cinfo->image_width);
  182. }
  183.  
  184.  
  185. METHODDEF void
  186. get_pseudocolor_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
  187. /* This is used for PSEUDOCOLOR images */
  188. {
  189.   long col;
  190.   JSAMPROW image_ptr, ptr0, ptr1, ptr2;
  191.   int val;
  192.  
  193.   cur_row_number--;        /* work down in array */
  194.   
  195.   image_ptr = *((*cinfo->emethods->access_big_sarray)
  196.         (image, cur_row_number, FALSE));
  197.  
  198.   ptr0 = pixel_row[0];
  199.   ptr1 = pixel_row[1];
  200.   ptr2 = pixel_row[2];
  201.   
  202.   for (col = cinfo->image_width; col > 0; col--) {
  203.     val = GETJSAMPLE(*image_ptr++);
  204.     *ptr0++ = colormap[val      ] >> 8;
  205.     *ptr1++ = colormap[val + 256] >> 8;
  206.     *ptr2++ = colormap[val + 512] >> 8;
  207.   }
  208. }
  209.  
  210.  
  211. METHODDEF void
  212. get_truecolor_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
  213. /* This is used for TRUECOLOR images */
  214. /* The colormap consists of 3 independent lookup tables */
  215. {
  216.   long col;
  217.   JSAMPROW red_ptr, green_ptr, blue_ptr, ptr0, ptr1, ptr2;
  218.   
  219.   cur_row_number--;        /* work down in array */
  220.   
  221.   red_ptr   = *((*cinfo->emethods->access_big_sarray)
  222.         (red_channel, cur_row_number, FALSE));
  223.   green_ptr = *((*cinfo->emethods->access_big_sarray)
  224.         (green_channel, cur_row_number, FALSE));
  225.   blue_ptr  = *((*cinfo->emethods->access_big_sarray)
  226.         (blue_channel, cur_row_number, FALSE));
  227.   
  228.   ptr0 = pixel_row[0];
  229.   ptr1 = pixel_row[1];
  230.   ptr2 = pixel_row[2];
  231.   
  232.   for (col = cinfo->image_width; col > 0; col--) {
  233.     *ptr0++ = colormap[GETJSAMPLE(*red_ptr++)        ] >> 8;
  234.     *ptr1++ = colormap[GETJSAMPLE(*green_ptr++) + 256] >> 8;
  235.     *ptr2++ = colormap[GETJSAMPLE(*blue_ptr++)  + 512] >> 8;
  236.   }
  237. }
  238.  
  239.  
  240. METHODDEF void
  241. get_directcolor_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
  242. /* This is used for DIRECTCOLOR images */
  243. {
  244.   JSAMPROW inputrows[3];    /* a pseudo JSAMPARRAY structure */
  245.  
  246.   cur_row_number--;        /* work down in array */
  247.   
  248.   inputrows[0] = *((*cinfo->emethods->access_big_sarray)
  249.             (red_channel, cur_row_number, FALSE));
  250.   inputrows[1] = *((*cinfo->emethods->access_big_sarray)
  251.             (green_channel, cur_row_number, FALSE));
  252.   inputrows[2] = *((*cinfo->emethods->access_big_sarray)
  253.             (blue_channel, cur_row_number, FALSE));
  254.  
  255.   jcopy_sample_rows(inputrows, 0, pixel_row, 0, 3, cinfo->image_width);
  256. }
  257.  
  258.  
  259. /*
  260.  * Load the color channels into separate arrays.  We have to do
  261.  * this because RLE files start at the lower left while the JPEG standard
  262.  * has them starting in the upper left.  This is called the first time
  263.  * we want to get a row of input.  What we do is load the RLE data into
  264.  * big arrays and then call the appropriate routine to read one row from
  265.  * the big arrays.  We also change cinfo->methods->get_input_row so that
  266.  * subsequent calls go straight to the row-reading routine.
  267.  */
  268.  
  269. METHODDEF void
  270. load_image (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
  271. {
  272.   long row;
  273.   rle_pixel *rle_row[3];
  274.   
  275.   /* Read the RLE data into our virtual array(s).
  276.    * We assume here that (a) rle_pixel is represented the same as JSAMPLE,
  277.    * and (b) we are not on a machine where FAR pointers differ from regular.
  278.    */
  279.   RLE_CLR_BIT(header, RLE_ALPHA); /* don't read the alpha channel */
  280.  
  281.   switch (visual) {
  282.   case GRAYSCALE:
  283.   case PSEUDOCOLOR:
  284.     for (row = 0; row < cinfo->image_height; row++) {
  285.       /*
  286.        * Read a row of the image directly into our big array.
  287.        * Too bad this doesn't seem to return any indication of errors :-(.
  288.        */
  289.       rle_row[0] = (rle_pixel *) *((*cinfo->emethods->access_big_sarray)
  290.                     (image, row, TRUE));
  291.       rle_getrow(&header, rle_row);
  292.     }
  293.     break;
  294.   case TRUECOLOR:
  295.   case DIRECTCOLOR:
  296.     for (row = 0; row < cinfo->image_height; row++) {
  297.       /*
  298.        * Read a row of the image directly into our big arrays.
  299.        * Too bad this doesn't seem to return any indication of errors :-(.
  300.        */
  301.       rle_row[0] = (rle_pixel *) *((*cinfo->emethods->access_big_sarray)
  302.                     (red_channel, row, TRUE));
  303.       rle_row[1] = (rle_pixel *) *((*cinfo->emethods->access_big_sarray)
  304.                     (green_channel, row, TRUE));
  305.       rle_row[2] = (rle_pixel *) *((*cinfo->emethods->access_big_sarray)
  306.                     (blue_channel, row, TRUE));
  307.       rle_getrow(&header, rle_row);
  308.     }
  309.     break;
  310.   }
  311.   
  312.   /* Set up to call proper row-extraction routine in future */
  313.   switch (visual) {
  314.   case GRAYSCALE:
  315.     cinfo->methods->get_input_row = get_grayscale_row;
  316.     break;
  317.   case PSEUDOCOLOR:
  318.     cinfo->methods->get_input_row = get_pseudocolor_row;
  319.     break;
  320.   case TRUECOLOR:
  321.     cinfo->methods->get_input_row = get_truecolor_row;
  322.     break;
  323.   case DIRECTCOLOR:
  324.     cinfo->methods->get_input_row = get_directcolor_row;
  325.     break;
  326.   }
  327.  
  328.   /* And fetch the topmost (bottommost) row */
  329.   cur_row_number = cinfo->image_height;
  330.   (*cinfo->methods->get_input_row) (cinfo, pixel_row);   
  331. }
  332.  
  333.  
  334. /*
  335.  * Finish up at the end of the file.
  336.  */
  337.  
  338. METHODDEF void
  339. input_term (compress_info_ptr cinfo)
  340. {
  341.   switch (visual) {
  342.   case GRAYSCALE:
  343.   case PSEUDOCOLOR:
  344.     (*cinfo->emethods->free_big_sarray) (image);
  345.     break;
  346.   case TRUECOLOR:
  347.   case DIRECTCOLOR:
  348.     (*cinfo->emethods->free_big_sarray) (red_channel);
  349.     (*cinfo->emethods->free_big_sarray) (green_channel);
  350.     (*cinfo->emethods->free_big_sarray) (blue_channel);
  351.     break;
  352.   }
  353. }
  354.  
  355.  
  356. /*
  357.  * The method selection routine for RLE format input.
  358.  * Note that this must be called by the user interface before calling
  359.  * jpeg_compress.  If multiple input formats are supported, the
  360.  * user interface is responsible for discovering the file format and
  361.  * calling the appropriate method selection routine.
  362.  */
  363.  
  364. GLOBAL void
  365. jselrrle (compress_info_ptr cinfo)
  366. {
  367.   cinfo->methods->input_init    = input_init;
  368.   cinfo->methods->get_input_row = load_image; /* until first call */
  369.   cinfo->methods->input_term    = input_term;
  370. }
  371.  
  372. #endif /* RLE_SUPPORTED */
  373.